/* Copyright (c) 2011 Alexandre Défossez
 * This file is part of HINAPT.
 *
 * HINAPT is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * HINAPT is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with HINAPT.  If not, see <http://www.gnu.org/licenses/>.
 */


#include "EyeDetector.hpp"

EyeDetector::EyeDetector(string leftEyeCascadeFile,
                         string rightEyeCascadeFile,
                         string faceCascadeFile)
{
  eyeClassifier[0].load(leftEyeCascadeFile);
  eyeClassifier[1].load(rightEyeCascadeFile);
  faceClassifier.load(faceCascadeFile);
  Assert(!eyeClassifier[0].empty(), "Couln't load left eye classifier");
  Assert(!eyeClassifier[1].empty(), "Couln't load right eye classifier");
  Assert(!faceClassifier.empty(), "Couln't load face classifier");
}



bool EyeDetector::find(Mat &img, Point2f &leftEye, Point2f &rightEye){
  Rect le, re;
  if (!find(img, le, re))
    return false;
  leftEye = center(le);
  rightEye = center(re);
  return true;
}


bool EyeDetector::find(Mat &img, Rect &leftEye, Rect &rightEye){
  vector<Rect> faces;
  Mat leftPart, rightPart;

  // On commence par chercher des têtes
  faceClassifier.detectMultiScale(img, faces, 1.1, 3, 0, Size(img.cols/7., img.rows/7.));

  for(size_t i=0; i<faces.size(); i++){
    /*
      On découpe la tête et on cherche en haut à gauche et en haut à droite
      un œil.
    */
    Rect roi = faces[i];
    roi.height = roi.height/2;
    Rect lroi = roi;
    lroi.width = lroi.width/2;
    Rect rroi = roi;
    rroi.width = roi.width/2;
    rroi.x += rroi.width;

    leftPart = Mat(img, lroi);
    rightPart = Mat(img, rroi);

    bool success = true;

    vector<Rect> eyes[2];

    #pragma omp parallel for reduction(&:success)
    for(int i=0; i<2; i++){
      Mat part = (i==0)?leftPart:rightPart;
      eyeClassifier[i].detectMultiScale(part, eyes[i], 1.1, 3, 0, Size(part.cols/6, part.rows/6));
      success &= !eyes[i].empty();
    }

    if (!success)
        continue;

    leftEye = eyes[0][0];
    rightEye = eyes[1][0];

    leftEye.x += lroi.x;
    leftEye.y += lroi.y;
    rightEye.x += rroi.x;
    rightEye.y += rroi.y;
    return true;
  }
  return false;
}

